﻿using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace Fast.RemoteRequest
{
    [SkipScan]
    public static class HttpRemoteRequestExtensions
    {
        /// <summary>
        /// 发送 GET 请求
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<HttpResponseMessage> GetAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendAsync(HttpMethod.Get, cancellationToken);
        }

        /// <summary>
        /// 发送 Get 请求返回 T 对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<T> GetAsync<T>(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendAsync<T>(HttpMethod.Get, cancellationToken);
        }

        /// <summary>
        /// 发送 Get 请求返回 String
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<string> GetStringAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            var response = await request.SendAsync(HttpMethod.Get, cancellationToken);
            if (response?.Content == null) return default;

            // 读取响应报文
            var content = await response.Content.ReadAsStringAsync(cancellationToken);
            return content;
        }

        /// <summary>
        /// 发送 Get 请求返回 Stream
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<Stream> GetStreamAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return await request.SendStreamAsync(HttpMethod.Get, cancellationToken);
        }

        /// <summary>
        /// 发送 POST 请求
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<HttpResponseMessage> PostAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendAsync(HttpMethod.Post, cancellationToken);
        }

        /// <summary>
        /// 发送 POST 请求返回 T 对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<T> PostAsync<T>(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendAsync<T>(HttpMethod.Post, cancellationToken);
        }

        /// <summary>
        /// 发送 POST 请求返回 String
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<string> PostStringAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendStringAsync(HttpMethod.Post, cancellationToken);
        }

        /// <summary>
        /// 发送 POST 请求返回 Stream
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<Stream> PostStreamAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendStreamAsync(HttpMethod.Post, cancellationToken);
        }

        /// <summary>
        /// 发送 PUT 请求
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<HttpResponseMessage> PutAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendAsync(HttpMethod.Put, cancellationToken);
        }

        /// <summary>
        /// 发送 PUT 请求返回 T 对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<T> PutAsync<T>(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendAsync<T>(HttpMethod.Put, cancellationToken);
        }

        /// <summary>
        /// 发送 PUT 请求返回 String
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<string> PutStringAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendStringAsync(HttpMethod.Put, cancellationToken);
        }

        /// <summary>
        /// 发送 PUT 请求返回 Stream
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<Stream> PutStreamAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendStreamAsync(HttpMethod.Put, cancellationToken);
        }

        /// <summary>
        /// 发送 DELETE 请求
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<HttpResponseMessage> DeleteAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendAsync(HttpMethod.Delete, cancellationToken);
        }

        /// <summary>
        /// 发送 DELETE 请求返回 T 对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<T> DeleteAsync<T>(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendAsync<T>(HttpMethod.Delete, cancellationToken);
        }

        /// <summary>
        /// 发送 DELETE 请求返回 String
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<string> DeleteStringAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendStringAsync(HttpMethod.Delete, cancellationToken);
        }

        /// <summary>
        /// 发送 DELETE 请求返回 Stream
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<Stream> DeleteStreamAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendStreamAsync(HttpMethod.Delete, cancellationToken);
        }

        /// <summary>
        /// 发送 PATCH 请求
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<HttpResponseMessage> PatchAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendAsync(HttpMethod.Patch, cancellationToken);
        }

        /// <summary>
        /// 发送 PATCH 请求返回 T 对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<T> PatchAsync<T>(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendAsync<T>(HttpMethod.Patch, cancellationToken);
        }

        /// <summary>
        /// 发送 Patch 请求返回 String
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<string> PatchAsStringAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendStringAsync(HttpMethod.Patch, cancellationToken);
        }

        /// <summary>
        /// 发送 PATCH 请求返回 Stream
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<Stream> PatchAsStreamAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendStreamAsync(HttpMethod.Patch, cancellationToken);
        }

        /// <summary>
        /// 发送 HEAD 请求返回 T 对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<T> HeadAsync<T>(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendAsync<T>(HttpMethod.Head, cancellationToken);
        }

        /// <summary>
        /// 发送 HEAD 请求返回 Stream
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<Stream> HeadStreamAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendStreamAsync(HttpMethod.Head, cancellationToken);
        }

        /// <summary>
        /// 发送 Head 请求返回 String
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<string> HeadAsStringAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendStringAsync(HttpMethod.Head, cancellationToken);
        }

        /// <summary>
        /// 发送 HEAD 请求
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static Task<HttpResponseMessage> HeadAsync(this IHttpRemoteRequest request, CancellationToken cancellationToken = default)
        {
            return request.SendAsync(HttpMethod.Head, cancellationToken);
        }

        /// <summary>
        /// 发送请求返回 T 对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="request"></param>
        /// <param name="httpMethod"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<T> SendAsync<T>(this IHttpRemoteRequest request, HttpMethod httpMethod, CancellationToken cancellationToken = default)
        {
            // 如果 T 是 HttpResponseMessage 类型，则返回
            if (typeof(T) == typeof(HttpResponseMessage))
            {
                var httpResponseMessage = await request.SendAsync(httpMethod, cancellationToken);
                return (T)(object)httpResponseMessage;
            }
            if (typeof(T) == typeof(string))
            {
                var str = await request.SendStringAsync(httpMethod, cancellationToken);
                return (T)(object)str;
            }

            // 读取流内容
            var stream = await request.SendStreamAsync(httpMethod, cancellationToken);
            if (stream == null) return default;

            // 如果 T 是 Stream 类型，则返回
            if (typeof(T) == typeof(Stream)) return (T)(object)stream;

            using var streamReader = new StreamReader(stream);
            var text = await streamReader.ReadToEndAsync();
            // 释放流
            await stream.DisposeAsync();

            // 如果字符串为空，则返回默认值
            if (string.IsNullOrWhiteSpace(text)) return default;

            // 反序列化流
            var result = App.JsonSerializer.Deserialize<T>(text);
            return result;
        }

        /// <summary>
        /// 发送请求返回 String
        /// </summary>
        /// <param name="request"></param>
        /// <param name="httpMethod"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async static Task<string> SendStringAsync(this IHttpRemoteRequest request, HttpMethod httpMethod, CancellationToken cancellationToken = default)
        {
            var response = await request.SendAsync(httpMethod, cancellationToken);
            if (response == null || response.Content == null) return default;

            // 读取响应报文
            var content = await response.Content.ReadAsStringAsync(cancellationToken);
            return content;
        }

        /// <summary>
        /// 发送请求返回 Stream
        /// </summary>
        /// <param name="request"></param>
        /// <param name="httpMethod"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async static Task<Stream> SendStreamAsync(this IHttpRemoteRequest request, HttpMethod httpMethod, CancellationToken cancellationToken = default)
        {
            var response = await request.SendAsync(httpMethod, cancellationToken);
            if (response == null || response.Content == null) return default;

            // 读取响应流
            var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
            return stream;
        }
    }
}
